package com.supermarket.manage.provider.ucenter.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.supermarket.manage.common.constant.RedisKeyConstant;
import com.supermarket.manage.common.constant.RoleConstant;
import com.supermarket.manage.common.constant.StatusConstant;
import com.supermarket.manage.common.dto.ucenter.request.RegisterParams;
import com.supermarket.manage.common.dto.ucenter.request.UserParams;
import com.supermarket.manage.common.dto.ucenter.response.MenuNode;
import com.supermarket.manage.common.pojo.Buyer;
import com.supermarket.manage.common.pojo.MyUser;
import com.supermarket.manage.common.pojo.Permission;
import com.supermarket.manage.common.utils.MenuUtil;
import com.supermarket.manage.provider.api.ucenter.UserService;
import com.supermarket.manage.provider.ucenter.mapper.UserMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author Faxon
 * @version 1.0
 * @date 2020-02-14 19:46
 **/
@Service(version = "1.0.0", timeout = 5000)
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private BuyerServiceImpl buyerService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public MyUser getUserByUsernameWithNoPermission(String username) {
        return userMapper.getUserByUserName(username);
    }

    @Override
    public MyUser getUserByUsername(String username) {
        MyUser myUser = getUserByUsernameWithNoPermission(username);
        if (null != myUser) {
            List<Permission> permissionList = userMapper.getPermissionListByUserId(myUser.getId());
            myUser.setPermissionList(permissionList);
        }
        return myUser;
    }

    @Override
    public MyUser userLoginByUsername(String username) {
        MyUser user = userMapper.getUserByUserName(username);
        if (null != user) {
            List<Permission> permissionList = userMapper.getPermissionListByUserId(user.getId());
            if(permissionList!=null && permissionList.size()>0){
                List<MenuNode> menus = MenuUtil.getMenuByPermissions(permissionList);
                user.setMenuList(menus);
            }
        }
        return user;
    }

    @Override
    public MyUser getUserByUserId(Long userId) {
        return userMapper.getUserById(userId);
    }


    @Override
    public Boolean updatePasswordById(Long id, String newPassword) {
        UpdateWrapper<MyUser> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", id);
        wrapper.set("password", newPassword);
        int update = userMapper.update(null, wrapper);
        return update == 1;
    }

    @Override
    public String getUsernameByUserId(Long id) {
        QueryWrapper<MyUser> wrapper = new QueryWrapper<>();
        wrapper.eq("id", id).eq("status", StatusConstant.USE);
        wrapper.select("username");
        MyUser myUser = userMapper.selectOne(wrapper);
        return myUser.getUsername();
    }

    @Override
    public Integer getCountByUsername(String username) {
        QueryWrapper<MyUser> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username).eq("status", StatusConstant.USE);
        return userMapper.selectCount(wrapper);
    }

    @Override
    public Boolean updateUserById(MyUser newUser) {
        String buyerId = newUser.getBuyerId();
        newUser.setBuyerId(null);
        //更新数据库
        int update = userMapper.updateById(newUser);
        //更新redis
        if (update == 1) {
            BoundHashOperations<String, Long, String> ops = redisTemplate.<Long, String>boundHashOps(RedisKeyConstant.USER + buyerId);
            ops.put(newUser.getId(), JSON.toJSONString(newUser));
        }
        return update == 1;
    }

    @Override
    public Integer getCountByPhone(String phone) {
        QueryWrapper<MyUser> wrapper = new QueryWrapper<>();
        wrapper.eq("phone", phone).eq("status", StatusConstant.USE);
        return userMapper.selectCount(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean register(RegisterParams params) {
        //注册客户信息
        Buyer buyer = new Buyer();
        buyer.setShopName(params.getShopName());
        buyer.setName(params.getUsername());
        buyer.setPhone(params.getPhone());
        buyer.setCreated(new Date());
        buyer.setUpdated(new Date());
        String buyerId = buyerService.insertBuyer(buyer);
        if (StringUtils.isNotBlank(buyerId)) {
            //注册用户信息
            MyUser user = new MyUser();
            user.setUsername(params.getUsername());
            user.setPassword(params.getPassword());
            user.setPhone(params.getPhone());
            user.setBuyerId(buyerId);
            user.setStatus(StatusConstant.USE);
            user.setCreated(buyer.getCreated());
            user.setUpdated(buyer.getUpdated());
            user.setRoleId(RoleConstant.SUPER_MANAGER_ID);
            return insertUser(user) == 1;
        }
        return Boolean.FALSE;
    }

    @Override
    public Integer insertUser(MyUser user) {
        user.setStatus(StatusConstant.USE);
        int insert = userMapper.insert(user);
        if (insert == 1) {
            BoundHashOperations<String, Long, String> ops = redisTemplate.<Long, String>boundHashOps(RedisKeyConstant.USER + user.getBuyerId());
            if (ops.hasKey(user.getId())) {
                ops.put(user.getId(), JSON.toJSONString(user));
            } else {
                saveUsersToRedis(user.getBuyerId());
            }
        }
        return insert;
    }

    @Override
    public Boolean bindPhone(UserParams user) {
        //更新数据库
        MyUser myUser = new MyUser();
        myUser.setId(user.getId());
        myUser.setPhone(user.getPhone());
        myUser.setUpdated(new Date());
        int i = userMapper.updateById(myUser);
        //更新redis
        if (i == 1) {
            BoundHashOperations<String, Long, String> ops = redisTemplate.<Long, String>boundHashOps(RedisKeyConstant.USER + user.getBuyerId());
            String json = ops.get(user.getId());
            if (StringUtils.isBlank(json)) {
                saveUsersToRedis(user.getBuyerId());
            } else {
                MyUser newUser = JSON.parseObject(json, MyUser.class);
                newUser.setPhone(user.getPhone());
                ops.put(user.getId(), JSON.toJSONString(newUser));
            }
        }
        return i == 1;
    }

    @Override
    public Boolean untiePhone(UserParams params) {
        //更新数据库
        MyUser myUser = new MyUser();
        myUser.setId(params.getId());
        myUser.setPhone("");
        myUser.setUpdated(new Date());
        int i = userMapper.updateById(myUser);
        //更新redis
        if (i == 1) {
            BoundHashOperations<String, Long, String> ops = redisTemplate.<Long, String>boundHashOps(RedisKeyConstant.USER + params.getBuyerId());
            String json = ops.get(params.getId());
            if (StringUtils.isBlank(json)) {
                saveUsersToRedis(params.getBuyerId());
            } else {
                MyUser user = JSON.parseObject(json, MyUser.class);
                user.setPhone("");
                ops.put(user.getId(), JSON.toJSONString(user));
            }
        }
        return i == 1;
    }

    @Override
    public List<MyUser> getUserByBuyerId(String buyerId) {
        BoundHashOperations<String, Long, String> ops = redisTemplate.<Long, String>boundHashOps(RedisKeyConstant.USER + buyerId);
        List<String> values = ops.values();
        //redis为空，从数据库中获取
        if (values == null || values.size() == 0) {
            QueryWrapper<MyUser> wrapper = new QueryWrapper<>();
            wrapper.eq("buyer_id", buyerId).eq("status", StatusConstant.USE);
            List<MyUser> users = userMapper.selectList(wrapper);
            Map<Long, String> map = new HashMap<>(users.size());
            users.forEach(u -> {
                u.setPassword(null);
                map.put(u.getId(), JSON.toJSONString(u));
            });
            if (map.size() > 0) {
                ops.putAll(map);
            }
            return users;
        }
        //redis中有值，直接返回
        else {
            List<MyUser> redisUser = new ArrayList<>();
            values.forEach(v -> {
                MyUser user = JSON.parseObject(v, MyUser.class);
                redisUser.add(user);
            });
            return redisUser;
        }
    }

    /**
     * 同步用户信息到redis
     *
     * @param buyerId
     */
    private void saveUsersToRedis(String buyerId) {
        BoundHashOperations<String, Long, String> ops = redisTemplate.<Long, String>boundHashOps(RedisKeyConstant.USER + buyerId);
        QueryWrapper<MyUser> wrapper = new QueryWrapper<>();
        wrapper.eq("buyer_id", buyerId).eq("status", StatusConstant.USE);
        List<MyUser> users = userMapper.selectList(wrapper);
        Map<Long, String> map = new HashMap<>(users.size());
        users.forEach(u -> {
            u.setPassword(null);
            map.put(u.getId(), JSON.toJSONString(u));
        });
        if (map.size() > 0) {
            ops.putAll(map);
        }
    }
}
